﻿using System;
using System.Text;
using System.Web;
using NopSolutions.NopCommerce.BusinessLogic.Infrastructure;
using NopSolutions.NopCommerce.BusinessLogic.Services;
using NopSolutions.NopCommerce.Controls;
using System.Collections.Generic;
using NopSolutions.NopCommerce.BusinessLogic.Infrastructure.Caching;

namespace NopSolutions.NopCommerce.Web.Modules
{
    public partial class SiteMenu : BaseNopUserControl
    {
        private const string SITE_MENU = "SITE_MENU";

        private IBlogService _blogService;
        private IForumService _forumService;
        private ICacheManager _cacheManager;

        public SiteMenu() {
            _blogService = IoC.Resolve<IBlogService>();
            _forumService = IoC.Resolve<IForumService>();

            _cacheManager = IoC.Resolve<ICacheManager>();
        }

        protected override void OnInit(EventArgs e) {
            Load += new EventHandler(TopMenuUserControl_Load);

            base.OnInit(e);
        }

        public string CssClass { get; set; }

        void TopMenuUserControl_Load(object sender, EventArgs e) {
            BuildMenu();
        }

        private void BuildMenu() {
            SiteMapProvider siteMapProvider = SiteMap.Providers["NopWebXmlSiteMapProvider"];
            if (siteMapProvider == null) {
                Visible = false;
                return;
            }

            NopMenu menu = _cacheManager.Get(SITE_MENU) as NopMenu;
            if (menu == null) {
                menu = new NopMenu();
                if (!string.IsNullOrWhiteSpace(CssClass)) {
                    menu.CssClass = CssClass;
                }

                menu.Children = new List<NopMenuItem>();
                foreach (SiteMapNode node in siteMapProvider.RootNode.ChildNodes) {
                    var menuItem = BuildMenu(node, 0);

                    if (menuItem != null) {
                        menu.Children.Add(menuItem);
                    }
                }

                if (menu.Children != null && menu.Children.Count > 0) {
                    _cacheManager.Add(SITE_MENU, menu);
                }
            }

            var sb = new StringBuilder();
            if (menu.Children != null && menu.Children.Count > 0) {
                sb.AppendFormat("<ul class=\"{0}\">", menu.CssClass);

                foreach (var item in menu.Children) {
                    RenderMenu(sb, item, 0);
                    //BuildMenuRecursive(sb, node, 0);
                }

                sb.Append("</ul>");
            }
            litTopMenu.Text = sb.ToString();
        }

        private NopMenuItem BuildMenu(SiteMapNode node, int level) {
            var menuItem = new NopMenuItem();

            switch (node.Title) {
                case "Blog":
                    if (!_blogService.BlogEnabled)
                        return null;
                    break;
                case "Forum":
                    if (!_forumService.ForumsEnabled)
                        return null;
                    break;
            }

            menuItem.Title = HttpUtility.HtmlEncode(!String.IsNullOrEmpty(node["resourceTitle"]) ? GetLocaleResourceString(node["resourceTitle"]) : node.Title);
            menuItem.Url = String.IsNullOrEmpty(node.Url) ? "#" : node.Url;
            menuItem.CssClass = HttpUtility.HtmlEncode(!String.IsNullOrEmpty(node["cssClass"]) ? node["cssClass"] : "menu-item");

            if (node.HasChildNodes) {
                menuItem.Children = new List<NopMenuItem>();

                level++;
                foreach (SiteMapNode childNode in node.ChildNodes) {                    
                    var childMenuItem = BuildMenu(childNode, level);

                    if (childMenuItem != null) {
                        menuItem.Children.Add(childMenuItem);
                    }
                }
            }

            return menuItem;
        }

        private void RenderMenu(StringBuilder sb, NopMenuItem item, int level) {
            string itemCssClass = string.Empty;
            if (item.Children != null && item.Children.Count > 0) {
                itemCssClass = "has-children";
            }
            if (item.Url == Request.Url.AbsolutePath) {
                itemCssClass += " active";
            }

            sb.AppendFormat("<li class=\"{0}\">", itemCssClass);

            sb.AppendFormat("<a href=\"{0}\" class=\"{1}\">{2}</a>", item.Url, item.CssClass, item.Title);

            if (item.Children != null && item.Children.Count > 0) {
                sb.Append("<ul class=\"flyout\">");
                foreach (var child in item.Children) {
                    level++;
                    RenderMenu(sb, child, level);
                }
                sb.Append("</ul>");
            }

            sb.Append("</li>");
        }

        private void BuildMenuRecursive(StringBuilder sb, SiteMapNode node, int level) {

            switch (node.Title) {
                case "Blog":
                    if (!_blogService.BlogEnabled)
                        return;
                    break;
                case "Forum":
                    if (!_forumService.ForumsEnabled)
                        return;
                    break;
            }

            string title = HttpUtility.HtmlEncode(!String.IsNullOrEmpty(node["resourceTitle"]) ? GetLocaleResourceString(node["resourceTitle"]) : node.Title);
            string linkCssClass = HttpUtility.HtmlEncode(!String.IsNullOrEmpty(node["cssClass"]) ? node["cssClass"] : "menu-item");
            string itemCssClass = string.Empty;

            if (node.HasChildNodes)
                itemCssClass = "has-children";
            // current node
            if (node.Url == Request.Url.AbsolutePath || node.Url.ToLower().Equals("/default.aspx"))
                itemCssClass += " active";

            sb.Append("<li class=\"" + itemCssClass + "\">");
            sb.AppendFormat("<a href=\"{0}\" class=\"{1}\">{2}</a>", (String.IsNullOrEmpty(node.Url) ? "#" : node.Url), linkCssClass, title);
            if (node.HasChildNodes) {
                sb.Append("<ul class=\"flyout\">");
                foreach (SiteMapNode childNode in node.ChildNodes) {
                    BuildMenuRecursive(sb, childNode, level++);
                }
                sb.Append("</ul>");
            }
            sb.Append("</li>");
        }
    }
}